--[=[
 规则

]=]


local table_insert = table.insert
local table_remove = table.remove
local math_random = math.random

local M = class("Rule")






-- to localeger
local function int(f)
    if f >= 0 then return math.floor(f)
    else return math.ceil(f)
    end
end

------------------------------------------------

local win_width = 800
local win_height = 500
local BALL =
{
    -- local X, Y, dir, gapt 球的坐标，方向，摩擦力
    -- local kind 球的类型 0-7
    -- local stop, goin 球是否停止，是否进洞
    -- LONGLONG Lt1, Lt2 时间，Lt2-Lt1 > gapt 决定球运动时间长短
}



-- 球的初始坐标
local iix = { 0,
              1, 1,
              2, 2, 2,
              3, 3, 3, 3,
              4, 4, 4, 4, 4,
              180, 180, 180, 400, 581, 740, -80 }

local iiy = { 0,
              -1, 1,
              -2, 0, 2,
              -3, -1, 1, 3,
              -4, -2, 0, 2, 4,
              350, 150, 250, 250, 250, 250, -250 }
-- 减速时的加速度
local slow = { 0.01, 0.02, 0.05, 0.1, 0.11, 0.14 }


local function gettime()
    return g.getMsec()
end


function M:ctor()

    --桌子的边界
    self.sx = 38
    self.ex = 762
    self.sy = 38
    self.ey = 462

    --6个洞的坐标
    self.holes = {
        {x=44, y=44},
        {x=44, y=456},
        {x=756, y=44},
        {x=756, y=456},
        {x=400, y=40},
        {x=400, y=460},
    }

    --球的个数
    self.balls_num = 22

    --移动速度
    self.speed = 3

    self.r = 13 --小球半径
    self.R = 26 --小球直径

    self:shuffle()
end

function M:shuffle()
    self.balls = {}
    for i = 1, 15 do
        self.balls[i] = {}
        self.balls[i].x = 610 + (iix[i] * 13 * math.sqrt(3.2))
        self.balls[i].y = 250 + iiy[i] * 13.7
        self.balls[i].stop = true
        self.balls[i].goin = false
        self.balls[i].kind = 7
        self.balls[i].gapt = 99999
        self.balls[i].Lt1 = gettime()
        self.balls[i].Lt2 = gettime()
    end
    for i = 16, 22 do
        self.balls[i] = {}
        self.balls[i].x = iix[i]
        self.balls[i].y = iiy[i]
        self.balls[i].kind = i - 16
        self.balls[i].stop = true
        self.balls[i].goin = false
        self.balls[i].gapt = 99999
        self.balls[i].Lt1 = gettime()
        self.balls[i].Lt2 = gettime()
    end
    self.balls[22].goin = true
end


--检查是否碰撞与进洞
function M:check(id)
    local ball = self.balls[id]
    local cx = ball.x
    local cy = ball.y
    local a, b
    cx = cx + self.speed * math.cos(ball.dir)
    cy = cy - self.speed * math.sin(ball.dir)

    --if (cx <= 44 and cy <= 44 or  cx <= 44 and cy >= 456 or  cx >= 756 and cy <= 44 or  cx >= 756 and cy >= 456
    --        or cx >= 390 and cx <= 410 and cy <= 40 or cx >= 390 and cx <= 410 and cy >= 460)
    --then
    if (cx <= self.holes[1].x and cy <= self.holes[1].y) or (cx <= self.holes[2].x and cy >= self.holes[2].y) or
            (cx >= self.holes[3].x and cy <= self.holes[3].y) or (cx >= self.holes[4].x and cy >= self.holes[4].y) or
            (cx >= self.holes[5].x - 10 and cx <= self.holes[5].x + 10 and cy <= self.holes[5].y) or
            (cx >= self.holes[6].x - 10 and cx <= self.holes[6].x + 10 and cy >= self.holes[6].y) then
        if (id == 22) then
            --白球进洞了
            print("白球进洞了")
            self.balls[22].goin = true
            self.balls[22].stop = true
            return true
        else
            --球进了
            ball.x = -50
            ball.goin = true
            return true
        end
    end

    --在桌子范围内
    if (cx > self.sx and cx < self.ex and cy > self.sy and cy < self.ey) then
        for j = 1, 22 do
            if (j ~= id) then
                a = cx - self.balls[j].x
                b = cy - self.balls[j].y
                if (a * a + b * b < math.pow(self.R, 2)) then
                    --碰到别的球了
                    local slow_ball --慢球
                    local fast_ball --快球
                    --2个球都在动
                    if (ball.gapt >= self.balls[j].gapt and self.balls[j].stop == false) then
                        slow_ball = ball
                        fast_ball = self.balls[j]
                    end
                    if (ball.gapt < self.balls[j].gapt and self.balls[j].stop == false)	then
                        slow_ball = self.balls[j]
                        fast_ball = ball
                    end

                    --碰到的球是静止的
                    if (self.balls[j].stop == true) then
                        slow_ball = self.balls[j]
                        fast_ball = ball
                        self.balls[j].stop = false
                    end

                    fast_ball.gapt = fast_ball.gapt * 1.4 --让快球减速
                    slow_ball.gapt = fast_ball.gapt * 1.2
                    slow_ball.dir = math.atan((fast_ball.y - slow_ball.y)/( slow_ball.x - fast_ball.x))
                    --快球方向
                    if (fast_ball.dir > slow_ball.dir) then
                        if (slow_ball.dir < 0 and fast_ball.dir > 1.57) then --1.57 π/2
                            fast_ball.dir = slow_ball.dir + 4.71 -- 4.71 3π/2
                        else
                            fast_ball.dir = slow_ball.dir + 1.57
                        end
                    else
                        if (slow_ball.dir > 0 and fast_ball.dir < -1.57) then
                            fast_ball.dir = slow_ball.dir - 4.71
                        else
                            fast_ball.dir = slow_ball.dir - 1.57
                        end
                    end
                    ball.x = ball.x + self.speed * math.cos(ball.dir)
                    ball.y = ball.y - self.speed * math.sin(ball.dir)
                else
                    ball.x = cx
                    ball.y = cy
                end
            end
        end
    elseif (cx <= self.sx or cx >= self.ex) then
        --碰到左边/右边桌子
        ball.dir = 3.14 - ball.dir
    elseif (cy <= self.sy or cy >= self.ey) then
        --碰到上边/下边桌子
        ball.dir = -ball.dir
    end
    return false
end


--球停止时再检测一下有没有与别的球碰在一起
function M:checkStopHit(id)
    local ball = self.balls[id]
    local cx = ball.x
    local cy = ball.y
    local a, b
    --在桌子范围内
    if (cx > self.sx and cx < self.ex and cy > self.sy and cy < self.ey) then
        for j = 1, 22 do
            if (j ~= id) then
                a = cx - self.balls[j].x
                b = cy - self.balls[j].y
                if (a * a + b * b < 25*25) then
                    --碰到别的球了
                    local slow_ball --慢球
                    local fast_ball --快球
                    if ball.gapt >= self.balls[j].gapt then
                        slow_ball = ball
                        fast_ball = self.balls[j]
                    else
                        slow_ball = self.balls[j]
                        fast_ball = ball
                    end
                    fast_ball.gapt = 40 --让快球减速
                    slow_ball.gapt = 40
                    slow_ball.dir = math.atan2(fast_ball.y - slow_ball.y, slow_ball.x - fast_ball.x)
                    --快球方向
                    if (fast_ball.dir > slow_ball.dir) then
                        if (slow_ball.dir < 0 and fast_ball.dir > 1.57) then --1.57 π/2
                            fast_ball.dir = slow_ball.dir + 4.71 -- 4.71 3π/2
                        else
                            fast_ball.dir = slow_ball.dir + 1.57
                        end
                    else
                        if (slow_ball.dir > 0 and fast_ball.dir < -1.57)then
                            fast_ball.dir = slow_ball.dir - 4.71
                        else
                            fast_ball.dir = slow_ball.dir - 1.57
                        end
                    end
                    ball.stop = false
                    fast_ball.x = fast_ball.x + 1 * math.cos(fast_ball.dir)
                    fast_ball.y = fast_ball.y - 1 * math.sin(fast_ball.dir)
                    slow_ball.x = slow_ball.x + 1 * math.cos(slow_ball.dir)
                    slow_ball.y = slow_ball.y - 1 * math.sin(slow_ball.dir)
                    break
                end
            end
        end
    end
end

--检测一下有没有与别的球碰在一起
function M:checkCollision(id)
    local ball = self.balls[id]
    local cx = ball.x
    local cy = ball.y
    local a, b
    --print("1111", cx, cy)
    --在桌子范围内
    if cx > self.sx and cx < self.ex and cy > self.sy and cy < self.ey then
        for j = 1, 22 do
            if j ~= id then
                a = cx - self.balls[j].x
                b = cy - self.balls[j].y
                if (a * a + b * b) < 676 then
                    --碰到别的球了
                    return true
                end
            end
        end
    end
    return false
end

function M:slow(sid)
    local s = self.balls[sid].gapt
    if s < 18 then
        local i = int(s / 3) % #slow +1
        self.balls[sid].gapt = self.balls[sid].gapt + slow[i]
    else
        self.speed = 2
        self.balls[sid].gapt = self.balls[sid].gapt + 0.17
    end

    if s > 45 then
        self.balls[sid].stop = true
        self:checkStopHit(sid)
    end
end

function M:move()
    local drt = 0
    for nu = 1, 22 do
        drt = self.balls[nu].Lt2 - self.balls[nu].Lt1
        if drt > self.balls[nu].gapt and self.balls[nu].stop == false and self.balls[nu].goin == false then
            self:check(nu)
            self:slow(nu)
            self.balls[nu].Lt1 = self.balls[nu].Lt2
        end
    end
end

--桌子激活
function M:run()
    while(true) do
        for id = 1, self.balls_num  do
            self.balls[id].Lt2 = gettime()
        end
        self:move()
        g.sleep(1)
    end
end

--打球
function M:hitBall(power, x, y)
    local ball = self.balls[22]
    ball.dir = math.atan((ball.y - y)/( x - ball.x))
    ball.stop = false
    ball.gapt = power
end

--放下白球
function M:resetWhiteBall(x, y)
    local ball = self.balls[22]
    if (ball.goin == true) then
        local x1
        local y1, y2
        x1 = (x - 180) * (x - 180)
        y1 = 250 - math.sqrt(10000 - x1)
        y2 = 250 + math.sqrt(10000 - x1)
        ball.x = x
        ball.y = y
        if (x >= 80 and x <= 180 and y >= y1) then
            if not self:checkCollision(22) then
                ball.goin = false
            else
                print("碰到别的球了")
            end
        end
    end
end

--取小球
function M:getBalls()
    local balls = {}
    for k, v in pairs(self.balls) do
        local ball = {
            id = k,
            x = v.x,
            y = v.y,
            speed = v.speed,
            dir = v.dir,
            gapt = v.gapt,
            stop = v.stop,
            goin = v.goin,
        }
        table_insert(balls, ball)
    end
    return balls
end

function M:checkOver()
    for k, v in pairs(self.balls) do
        if k ~= 22 and not v.goin then
            return false
        end
    end
    return true
end







return M

